package com;

import java.io.*;
import java.net.Socket;
import java.net.URLConnection;
import java.nio.file.Files;
import java.util.Date;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;

public class RequestProcessor implements Runnable {

    private final static Logger logger = Logger.getLogger(RequestProcessor.class.getCanonicalName());

    private File rooDirectory;

    private String index_file = "index.html";

    private Socket conn;

    public RequestProcessor(File rooDirectory, String index_file, Socket conn) {
        if(rooDirectory.isFile()){
            throw new IllegalArgumentException("rootDirectory must be a directory");
        }
        try{
            rooDirectory = rooDirectory.getCanonicalFile();
        } catch (IOException e) {
            e.printStackTrace();
        }

        this.rooDirectory = rooDirectory;

        if(index_file != null) this.index_file = index_file;

        this.conn = conn;
    }

    private void sendHeader(Writer writer, String responseCode, String contentType, long length) throws IOException {

        writer.write(responseCode + "\r\n");

        Date now = new Date();

        writer.write("Date: " + now + "\r\n");

        writer.write("Server: JHTTP 2.0\r\n");

        writer.write("Content-length: " + length + "\r\n");

        writer.write("Content-type: " + contentType + "\r\n\r\n");

        writer.flush();
    }

    @Override
    public void run() {

        //安全检查
        String root = rooDirectory.getPath();

        try {
            OutputStream raw = new BufferedOutputStream(conn.getOutputStream());

            Writer writer = new OutputStreamWriter(raw,"US-ASCII");

            Reader reader = new InputStreamReader(new BufferedInputStream(conn.getInputStream()));

            StringBuilder requestLine = new StringBuilder(80);

            while (true){

                int c = reader.read();

                if(c == '\r' || c == '\n' || c == -1) break;

                requestLine.append((char)c);

            }

            String get = requestLine.toString();

            logger.info(conn.getRemoteSocketAddress() + " " + get);

            String[] tokens = get.split("\\s+");

            String method = tokens[0];

            String version = "";

            if(get.startsWith("GET")){
                //get请求
                String fileName = tokens[1];
                if(fileName.endsWith("/")) fileName += index_file;

//                System.out.println(fileName);
//
//                System.out.println(root);

                String contentType = URLConnection.getFileNameMap().getContentTypeFor(fileName);

                if(tokens.length > 2)
                    version = tokens[2];

                File theFile = new File(rooDirectory,fileName.substring(1,fileName.length()));

//                System.out.println(theFile.getCanonicalFile().toString());
//
//                File f = new File("index.html");
//
//                System.out.println(f.getCanonicalFile().toString());

                if(theFile.canRead() && theFile.getCanonicalFile().toString().startsWith(root)){

                    byte[] data = Files.readAllBytes(theFile.toPath());

                    if(version.startsWith("HTTP/")){
                        sendHeader(writer,"HTTP/1.0 200 OK",contentType,data.length);
                    }

                    raw.write(data);

                    raw.flush();

                }else{
                    //not found
                    String body = new StringBuilder("<html>\r\n")
                    .append("<head><title>File Not Found</title>\r\n</head>\r\n")
                    .append("<body>")
                    .append("<h1>HTTP Error 404: File not Found</h1>\r\n")
                    .append("</body></html>\r\n").toString();

                    if(version.startsWith("HTTP/")){
                        sendHeader(writer,"HTTP/1.0 404 File Not Found","text/html;charset=utf-8",body.length());
                    }

                    writer.write(body);
                    writer.flush();
                }
            }else{
                //方法不是get
                String body = new StringBuilder("<html>\r\n")
                        .append("<head><title>Not Implemented</title>\r\n</head>\r\n")
                        .append("<body>")
                        .append("<h1>HTTP Error 501: Not Implemented</h1>\r\n")
                        .append("</body></html>\r\n").toString();

                if(version.startsWith("HTTP/")){
                    sendHeader(writer,"HTTP/1.0 501 Not Implemented","text/html;charset=utf-8",body.length());
                }

                writer.write(body);
                writer.flush();
            }

        } catch (IOException e) {
            logger.log(Level.WARNING,"error talking to " + conn.getRemoteSocketAddress(),e);
        }finally {

            try {
                conn.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }
}
